ICE
authorTim Carey-Smith <tim@spork.in>
Fri, 25 Jul 2014 23:05:27 +0000 (16:05 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 31 Jul 2014 14:09:53 +0000 (07:09 -0700)
src/cargo/core/resolver.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_generate_lockfile.rs

index 7971fbb771e718cae9fcd171d71a5fd9bec8d362..5b4e8118407417506656a65e3a42f60add40624c 100644 (file)
@@ -1,6 +1,7 @@
 use std::collections::HashMap;
 use std::fmt;
 use serialize::{Encodable, Encoder};
+use serialize::{Encodable, Encoder, Decodable, Decoder};
 use util::graph::{Nodes,Edges};
 
 use core::{
@@ -21,15 +22,110 @@ pub struct Resolve {
 
 #[deriving(Encodable, Decodable, Show)]
 pub struct EncodableResolve {
-    package: Vec<EncodableDependency>
+    package: Vec<EncodableDependency>,
+    root: EncodableDependency
 }
 
-#[deriving(Encodable, Decodable, Show)]
-pub struct EncodableDependency{
+impl EncodableResolve {
+    pub fn to_resolve(&self, default: &SourceId) -> CargoResult<Resolve> {
+        let mut g = Graph::new();
+
+        add_pkg_to_graph(&mut g, &self.root, default);
+
+        for dep in self.package.iter() {
+            add_pkg_to_graph(&mut g, dep, default);
+        }
+
+        Ok(Resolve { graph: g, root: try!(self.root.to_package_id(default)) })
+    }
+}
+
+fn add_pkg_to_graph(g: &mut Graph<PackageId>,
+                    dep: &EncodableDependency,
+                    default: &SourceId)
+                    -> CargoResult<()>
+{
+    let package_id = try!(dep.to_package_id(default));
+    g.add(package_id.clone(), []);
+
+    match dep.dependencies {
+        Some(ref deps) => {
+            for edge in deps.iter() {
+                g.link(package_id.clone(), try!(edge.to_package_id(default)));
+            }
+        },
+        _ => ()
+    };
+
+    Ok(())
+}
+
+#[deriving(Encodable, Decodable, Show, PartialOrd, Ord, PartialEq, Eq)]
+pub struct EncodableDependency {
+    name: String,
+    version: String,
+    source: Option<SourceId>,
+    dependencies: Option<Vec<EncodablePackageId>>
+}
+
+impl EncodableDependency {
+    fn to_package_id(&self, default_source: &SourceId) -> CargoResult<PackageId> {
+        PackageId::new(
+            self.name.as_slice(),
+            self.version.as_slice(),
+            self.source.as_ref().unwrap_or(default_source))
+    }
+}
+
+#[deriving(Show, PartialOrd, Ord, PartialEq, Eq)]
+pub struct EncodablePackageId {
     name: String,
     version: String,
-    source: SourceId,
-    dependencies: Option<Vec<PackageId>>
+    source: Option<SourceId>
+}
+
+impl<E, S: Encoder<E>> Encodable<S, E> for EncodablePackageId {
+    fn encode(&self, s: &mut S) -> Result<(), E> {
+        let mut out = format!("{} {}", self.name, self.version);
+        self.source.as_ref().map(|s| {
+            out.push_str(format!(" ({})", s.to_url()).as_slice())
+        });
+        out.encode(s)
+    }
+}
+
+impl<E, D: Decoder<E>> Decodable<D, E> for EncodablePackageId {
+    fn decode(d: &mut D) -> Result<EncodablePackageId, E> {
+        let string: String = raw_try!(Decodable::decode(d));
+        let regex = regex!(r"^([^ ]+) ([^ ]+) (?:\(([^\)]+)\))?$");
+        let captures = regex.captures(string.as_slice()).expect("invalid serialized PackageId");
+
+        let name = captures.at(1);
+        let version = captures.at(2);
+
+        let source = captures.at(3);
+
+        let source_id = if source == "" {
+            None
+        } else {
+            Some(SourceId::from_url(source.to_string()))
+        };
+
+        Ok(EncodablePackageId {
+            name: name.to_string(),
+            version: version.to_string(),
+            source: source_id
+        })
+    }
+}
+
+impl EncodablePackageId {
+    fn to_package_id(&self, default_source: &SourceId) -> CargoResult<PackageId> {
+        PackageId::new(
+            self.name.as_slice(),
+            self.version.as_slice(),
+            self.source.as_ref().unwrap_or(default_source))
+    }
 }
 
 impl<E, S: Encoder<E>> Encodable<S, E> for Resolve {
@@ -40,21 +136,39 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Resolve {
         let encodable = ids.iter().filter_map(|&id| {
             if self.root == *id { return None; }
 
-            let deps = self.graph.edges(id).map(|edge| {
-                let mut deps = edge.map(|e| e.clone()).collect::<Vec<PackageId>>();
-                deps.sort();
-                deps
-            });
-
-            Some(EncodableDependency {
-                name: id.get_name().to_string(),
-                version: id.get_version().to_string(),
-                source: id.get_source_id().clone(),
-                dependencies: deps
-            })
+            Some(encodable_resolve_node(id, &self.graph))
         }).collect::<Vec<EncodableDependency>>();
 
-        EncodableResolve { package: encodable }.encode(s)
+        EncodableResolve {
+            package: encodable,
+            root: encodable_resolve_node(&self.root, &self.graph)
+        }.encode(s)
+    }
+}
+
+fn encodable_resolve_node(id: &PackageId, graph: &Graph<PackageId>) -> EncodableDependency {
+    let deps = graph.edges(id).map(|edge| {
+        let mut deps = edge.map(|e| {
+            encodable_package_id(e)
+        }).collect::<Vec<EncodablePackageId>>();
+        deps.sort();
+        deps
+    });
+
+
+    EncodableDependency {
+        name: id.get_name().to_string(),
+        version: id.get_version().to_string(),
+        source: Some(id.get_source_id().clone()),
+        dependencies: deps,
+    }
+}
+
+fn encodable_package_id(id: &PackageId) -> EncodablePackageId {
+    EncodablePackageId {
+        name: id.get_name().to_string(),
+        version: id.get_version().to_string(),
+        source: Some(id.get_source_id().clone()),
     }
 }
 
index 84464ce90a4404082d3de6cb7c1e889e85d11e59..367de1d15134d9d2f96f73c7dc4b47bc4d987438 100644 (file)
@@ -100,7 +100,7 @@ pub fn compile(manifest_path: &Path,
              &PackageSet::new(packages.as_slice()), &resolve, &sources, &mut config));
     }
 
-    //try!(ops::generate_lockfile(manifest_path, *shell, false));
+    try!(ops::generate_lockfile(manifest_path, *shell, false));
 
     let test_executables: Vec<String> = targets.iter()
         .filter_map(|target| {
index e68a93d71fe7a8ececd47b5340b7ce97b88d006d..9bea6159debf20fae72afb65f56fbc00b5c71c07 100644 (file)
@@ -48,33 +48,22 @@ fn write_resolve(resolve: Resolve) {
     let mut e = Encoder::new();
     resolve.encode(&mut e).unwrap();
 
-    let deps = e.toml.find(&"package".to_string()).unwrap().as_slice().unwrap();
     let mut out = String::new();
 
-    for dep in deps.iter() {
-        let dep = dep.as_table().unwrap();
-        out.push_str("[[package]]\n");
-        out.push_str(format!("name = {}\n", lookup(dep, "name")).as_slice());
-        out.push_str(format!("version = {}\n", lookup(dep, "version")).as_slice());
+    let root = e.toml.find(&"root".to_string()).unwrap();
 
-        dep.find(&"source".to_string()).map(|s| {
-          out.push_str(format!("source = {}\n", lookup(dep, "source")).as_slice());
-        });
+    println!("root={}", root);
 
-        dep.find(&"dependencies".to_string()).map(|s| {
-            let slice = s.as_slice().unwrap();
+    out.push_str("[root]\n");
+    emit_package(root.as_table().unwrap(), &mut out);
 
-            if !slice.is_empty() {
-                out.push_str("dependencies = [\n");
+    let deps = e.toml.find(&"package".to_string()).unwrap().as_slice().unwrap();
 
-                for child in s.as_slice().unwrap().iter() {
-                    out.push_str(format!("  {},\n", child).as_slice());
-                }
+    for dep in deps.iter() {
+        let dep = dep.as_table().unwrap();
 
-                out.push_str("]\n");
-            }
-            out.push_str("\n");
-        });
+        out.push_str("[[package]]\n");
+        emit_package(dep, &mut out);
     }
 
     let mut file = File::create(&Path::new("Cargo.lock"));
@@ -86,6 +75,30 @@ fn write_resolve(resolve: Resolve) {
     println!("{}", v);
 }
 
+fn emit_package(dep: &TreeMap<String, toml::Value>, out: &mut String) {
+    out.push_str(format!("name = {}\n", lookup(dep, "name")).as_slice());
+    out.push_str(format!("version = {}\n", lookup(dep, "version")).as_slice());
+
+    dep.find(&"source".to_string()).map(|s| {
+        out.push_str(format!("source = {}\n", lookup(dep, "source")).as_slice());
+    });
+
+    dep.find(&"dependencies".to_string()).map(|s| {
+        let slice = s.as_slice().unwrap();
+
+        if !slice.is_empty() {
+            out.push_str("dependencies = [\n");
+
+            for child in s.as_slice().unwrap().iter() {
+                out.push_str(format!("  {},\n", child).as_slice());
+            }
+
+            out.push_str("]\n");
+        }
+        out.push_str("\n");
+    });
+}
+
 fn lookup<'a>(table: &'a TreeMap<String, toml::Value>, key: &'static str) -> &'a toml::Value {
-    table.find(&key.to_string()).unwrap()
+    table.find(&key.to_string()).expect(format!("Didn't find {}", key).as_slice())
 }